package net.wangds.auth.job.ctrl;

import net.wangds.auth.grant.entity.GeneralGrantEntity;
import net.wangds.auth.grant.service.GrantService;
import net.wangds.auth.job.comp.GeneralJobComp;
import net.wangds.auth.job.entity.GeneralJobEntity;
import net.wangds.auth.job.entity.GeneralJobRoleRef;
import net.wangds.auth.module.Grant;
import net.wangds.auth.module.ResourceSchemaEnum;
import net.wangds.auth.resource.comp.GeneralResourceComp;
import net.wangds.auth.role.comp.GeneralRoleComp;
import net.wangds.auth.user.comp.GeneralUserComp;
import net.wangds.data.Tree;
import net.wangds.jpa.Sorts;
import net.wangds.jpa.comp.AbstractRemovedComp;
import net.wangds.jpa.ctrl.AbstractJpaCompCtrl;
import net.wangds.web.entrypoint.BaseMultipleResp;
import net.wangds.web.entrypoint.BaseResp;
import net.wangds.web.entrypoint.PagingForm;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.transaction.Transactional;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;


@RestController
@RequestMapping("/job")
public class JobCtrl extends AbstractJpaCompCtrl<GeneralJobEntity> {

    @Autowired
    private GeneralJobComp mmCmpJob;

    @Autowired
    private GeneralUserComp mmCmpUsr;
    @Autowired
    private GeneralRoleComp mmCmpRole;

    @Autowired
    private GrantService mmServGrant;

    @Autowired
    private GeneralResourceComp mmCmpRes;


    @Override
    protected AbstractRemovedComp<GeneralJobEntity> fetchJpaComp() {
        return mmCmpJob;
    }

    @Override
    protected BaseMultipleResp<GeneralJobEntity> listWithKeywords(PagingForm page) {
        return mmConvPage2Resp.convert(mmCmpJob.findByKeywords(page.getKeywords(), mmConvPf2Pr.convert(page)));
    }


    /**
     * 获得指定机构id的子机构树.
     * @param rootJobId 根机构.
     * @return 机构树.
     */
    @RequestMapping(value="/tree/{rootJobId}", method = RequestMethod.POST)
    public BaseMultipleResp<GeneralJobEntity> tree(
            @PathVariable(value="rootJobId", required = false) String rootJobId
    ){
        List<GeneralJobEntity> jobs = mmCmpJob.findAll(Sorts.createTm_asc);

        List<GeneralJobEntity> trees = Tree.trees(jobs);

        if(StringUtils.equals("-1",rootJobId)){
            return BaseMultipleResp.list(trees);
        }else {
            return BaseMultipleResp.list(jobs.stream().filter(c -> StringUtils.equals(rootJobId, c.getId())).collect(Collectors.toList()));
        }
    }


    @RequestMapping(value="/bindUser/{jobId}/{uid}", method = RequestMethod.POST)
    public BaseResp<Boolean> bindUser(
            @PathVariable("jobId") String jobId,
            @PathVariable("uid") String uid) {
        mmCmpJob.findById(jobId).ifPresent(job->{
            mmCmpUsr.findById(uid).ifPresent(usr->{
                mmCmpJob.bindUser(job, usr);
            });
        });
        return BaseResp.of(true);
    }


    @RequestMapping(value="/unbindUser/{jobId}/{uid}", method = RequestMethod.POST)
    public BaseResp<Boolean> unbindUser(@PathVariable("jobId") String jobId,
                           @PathVariable("uid") String uid) {
        mmCmpJob.findById(jobId).ifPresent(job->{
            mmCmpUsr.findById(uid).ifPresent(usr->{
                mmCmpJob.unbindUser(job, usr);
            });
        });
        return BaseResp.of(true);
    }


    @RequestMapping(value="/bindRole/{jobId}/{roleId}", method = RequestMethod.POST)
    public BaseResp<Boolean> bindRole(@PathVariable("jobId") String jobId,
                         @PathVariable("roleId") String roleId) {
        mmCmpJob.findById(jobId).ifPresent(job->{
            mmCmpRole.findById(roleId).ifPresent(role->{
                mmCmpJob.bindRole(job, role);
            });
        });
        return BaseResp.of(true);
    }


    @RequestMapping(value="/unbindRole/{jobId}/{roleId}", method = RequestMethod.POST)
    public BaseResp<Boolean> unbindRole(@PathVariable("jobId") String jobId,
                                        @PathVariable("roleId") String roleId) {

        mmCmpJob.findById(jobId).ifPresent(job->{
            mmCmpRole.findById(roleId).ifPresent(role->{
                mmCmpJob.unbindRole(job, role);
            });
        });
        return BaseResp.of(true);
    }



    @RequestMapping(value="/grantRes/{jobId}/{resId}/{privilege}", method = RequestMethod.POST)
    public BaseResp<Boolean> grantRes2Job(
           @PathVariable("jobId") String jobId,
           @PathVariable("resId") String resId,
           @PathVariable("privilege") int privilege){

        mmCmpJob.findById(jobId).ifPresent(job->{
            mmCmpRes.findById(resId).ifPresent(res->{
                mmServGrant.grant(res, job, privilege);
            });
        });

        return BaseResp.of(true);
    }

    @RequestMapping(value="/ungrantRes/{jobId}/{resId}/{privilege}", method = RequestMethod.POST)
    public BaseResp<Boolean> ungrantRes2Job(
            @PathVariable("jobId") String jobId,
            @PathVariable("resId") String resId,
            @PathVariable("privilege") int privilege
    ){

        mmCmpJob.findById(jobId).ifPresent(job->{
            mmCmpRes.findById(resId).ifPresent(res->{
                mmServGrant.ungrant(res, job, privilege);
            });
        });

        return BaseResp.of(true);
    }

    @Transactional
    @RequestMapping(value = "/{jobId}/roleIds", method = RequestMethod.POST)
    public BaseResp<? extends Collection<String>> loadJobRoleIds(
            @PathVariable("jobId") String jid) {
        BaseResp res = BaseResp.of(null);
        mmCmpJob.findById(jid).ifPresent(job ->
                res.body(mmCmpJob.loadRoles(jid).stream().map(GeneralJobRoleRef::getRoleId).collect(Collectors.toList())));
        return res;
    }

    @Transactional
    @RequestMapping(value = "/{jobId}/menuIds", method = RequestMethod.POST)
    public BaseResp<? extends Collection<String>> loadJobMenuIds(
            @PathVariable("jobId") String jid) {
        BaseResp res = BaseResp.of(null);
        mmCmpJob.findById(jid).ifPresent(job ->
                res.body(mmServGrant.listByOwnerIdAndSchemaAndAction(job.getId(), ResourceSchemaEnum.MENU, 15).stream().map(GeneralGrantEntity::getResId).collect(Collectors.toList())));
        return res;
    }

    @Transactional
    @RequestMapping(value = "/{jobId}/grants", method = RequestMethod.POST)
    public BaseResp<List<? extends Grant>> loadJobGrants(
            @PathVariable("jobId") String jobId) {

        BaseResp<List<? extends Grant>> res = BaseResp.of(null);
        mmCmpJob.findById(jobId).ifPresent(user -> {
            res.body(mmServGrant.listGrantedByOwnerId(jobId));
        });

        return res;
    }



}
